package org.pearl.boot.redis.config;

import org.pearl.boot.redis.serializer.ProtoStuffRedisSerializer;
import org.pearl.boot.redis.sub.SubMsgListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * Created by TD on 2021/5/12
 */
@EnableScheduling // 开启定时任务功能
@Configuration
public class RedisConfig {

    /**
     * 创建RedisTemplate
     *
     * @param redisConnectionFactory 连接工厂
     * @param <T>                    值类型
     * @return RedisTemplate
     */
    @Bean(name = "redisTemplate")
    public <T> RedisTemplate<String, T> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, T> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // String序列化对象
        RedisSerializer<String> stringRedisSerializer = RedisSerializer.string();
        // ProtoStuff序列化
        ProtoStuffRedisSerializer<T> protoStuffRedisSerializer = new ProtoStuffRedisSerializer<>();
        // 序列化配置=>Key
        redisTemplate.setKeySerializer(stringRedisSerializer); // 所有Key都设置为字符串，方便阅读
        redisTemplate.setHashKeySerializer(protoStuffRedisSerializer); //  设置Hash数据结构中的Key
        // 序列化配置=>Value
        redisTemplate.setValueSerializer(protoStuffRedisSerializer); // 所有Value, 序列化时存入二进制，boundValueOperations进行操作会有问题，需要设置为JSON或者String
        redisTemplate.setHashValueSerializer(protoStuffRedisSerializer);  //  Hash数据结构中的Value
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Autowired
    SubMsgListener subMsgListener;

    @Autowired
    MessageListenerAdapter messageListener;

    /**
     * 消息侦听器容器
     *
     * @param factory 连接工厂
     * @return RedisMessageListenerContainer
     */
    @Bean
    RedisMessageListenerContainer redisContainer(final RedisConnectionFactory factory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        container.addMessageListener(messageListener, new ChannelTopic("redis-channel"));
        return container;
    }

    /**
     * 消息监听适配器
     * MessageListenerAdapter
     *
     * @return
     */
    @Bean
    MessageListenerAdapter messageListener() {
        return new MessageListenerAdapter(subMsgListener);
    }
}
